﻿//===============================================================================
// Microsoft Innovation Centre - Western Europe
// Copyright (c) 2008 Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using Microsoft.WVB.Framework;
using Microsoft.WVB.Silverlight.Infrastructure;

namespace Microsoft.WVB.UI
{
    [TemplatePart(Name = MediaControls.ForwardButtonName, Type = typeof(Button)),
    TemplatePart(Name = MediaControls.BackwardButtonName, Type = typeof(Button)),
    TemplatePart(Name = MediaControls.PlayPauseButtonName, Type = typeof(CheckBox)),
    TemplatePart(Name = MediaControls.StopButtonName, Type = typeof(Button)),
    TemplatePart(Name = MediaControls.MuteButtonName, Type = typeof(ToggleButton)),
    TemplatePart(Name = MediaControls.VolumeSliderName, Type = typeof(Slider)),
    TemplatePart(Name = MediaControls.DownloadSliderName, Type = typeof(Slider)),
    TemplatePart(Name = MediaControls.TimelineSliderName, Type = typeof(Slider)),
    TemplatePart(Name = MediaControls.TotalDurationName, Type = typeof(TextBlock)),
    TemplatePart(Name = MediaControls.CurrentDurationName, Type = typeof(TextBlock)),
    TemplatePart(Name = MediaControls.FullScreenButtonName, Type = typeof(ToggleButton))]
    [TemplateVisualState(Name = VisualStates.StateNormal, GroupName = VisualStates.GroupCommon),
    TemplateVisualState(Name = VisualStates.StateMouseOver, GroupName = VisualStates.GroupCommon)]
    public class MediaControls : Control
    {
        private const string ForwardButtonName = "ForwardButton";
        private const string BackwardButtonName = "BackwardButton";
        private const string PlayPauseButtonName = "PlayPauseButton";
        private const string StopButtonName = "StopButton";
        private const string MuteButtonName = "MuteButton";
        private const string VolumeSliderName = "VolumeSlider";
        private const string DownloadSliderName = "DownloadSlider";
        private const string TimelineSliderName = "TimelineSlider";
        private const string TotalDurationName = "TotalDuration";
        private const string CurrentDurationName = "CurrentDuration";
        private const string FullScreenButtonName = "FullscreenButton";

        public IPlayerModel ViewModel { get; private set; }

        public Button ForwardButton
        {
            get { return _ForwardButton; }
            set { _ForwardButton = value; }
        }
        private Button _ForwardButton;

        public Button BackwardButton
        {
            get { return _BackwardButton; }
            set { _BackwardButton = value; }
        }
        private Button _BackwardButton;

        public CheckBox PlayPauseButton
        {
            get { return _PlayPauseButton; }
            set { _PlayPauseButton = value; }
        }
        private CheckBox _PlayPauseButton;

        public Button StopButton
        {
            get { return _StopButton; }
            set { _StopButton = value; }
        }
        private Button _StopButton;

        public ToggleButton MuteButton
        {
            get { return _MuteButton; }
            set { _MuteButton = value; }
        }
        private ToggleButton _MuteButton;

        public Slider VolumeSlider
        {
            get { return _VolumeSlider; }
            set { _VolumeSlider = value;  }
        }
        private Slider _VolumeSlider;

        public Slider DownloadSlider
        {
            get { return _DownloadSlider; }
            set { _DownloadSlider = value;  }
        }
        private Slider _DownloadSlider;

        public Slider TimelineSlider
        {
            get { return _TimelineSlider; }
            set { _TimelineSlider = value; }
        }
        private Slider _TimelineSlider;

        public TextBlock TotalDuration
        {
            get { return _TotalDuration; }
            set { _TotalDuration = value; }
        }
        private TextBlock _TotalDuration;

        public TextBlock CurrentDuration
        {
            get { return _CurrentDuration; }
            set { _CurrentDuration = value; }
        }
        private TextBlock _CurrentDuration;

        public ToggleButton FullScreenButton
        {
            get { return _FullScreenButton; }
            set { _FullScreenButton = value; }
        }
        private ToggleButton _FullScreenButton;

        public Boolean IsMouseOver
        {
            get { return (Boolean)GetValue(IsMouseOverProperty); }
            set { SetValue(IsMouseOverProperty, value); }
        }
        public static readonly DependencyProperty IsMouseOverProperty = null;

        static MediaControls()
        {
            IsMouseOverProperty = DependencyProperty.Register("IsMouseOver", typeof(Boolean), typeof(MediaControls), new PropertyMetadata(false));
        }

        public MediaControls() : base()
        {
            this.DefaultStyleKey = typeof(MediaControls);

            if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            {
                this.ViewModel = IoC.GetCreate<IPlayerModel>();
                this.DataContext = ViewModel;
            }           
        }

        internal void UpdateVisualState()
        {
            this.ChangeVisualState(true);
        }

        internal void ChangeVisualState()
        {
            this.ChangeVisualState(true);
        }

        protected override void OnMouseEnter(MouseEventArgs e)
        {
            base.OnMouseEnter(e);
            this.IsMouseOver = true;
            UpdateVisualState();
        }

        protected override void OnMouseLeave(MouseEventArgs e)
        {
            base.OnMouseLeave(e);
            this.IsMouseOver = false;
            UpdateVisualState();
        }

        internal void ChangeVisualState(bool useTransitions)
        {
            if (this.IsMouseOver)
            {
                VisualStates.GoToState(this, useTransitions, new String[] { VisualStates.StateMouseOver });
            }
            else
            {
                VisualStates.GoToState(this, useTransitions, new String[] { VisualStates.StateNormal });
            }
        }

        public override void OnApplyTemplate()
        {
            RoutedEventHandler fwHandler = null;
            RoutedEventHandler bckwdHandler = null;
            RoutedEventHandler playPauseCheckhandler = null;
            RoutedEventHandler playPauseUnCheckHandler = null;
            RoutedEventHandler stopHandler = null;
            RoutedEventHandler muteCheckHandler = null;
            RoutedEventHandler muteUncheckHandler = null;
            RoutedPropertyChangedEventHandler<double> volumeHandler = null;
            RoutedPropertyChangedEventHandler<double> timelineHandler = null;

            base.OnApplyTemplate();

            this.ForwardButton = base.GetTemplateChild(MediaControls.ForwardButtonName) as Button;
            this.BackwardButton = base.GetTemplateChild(MediaControls.BackwardButtonName) as Button;
            this.PlayPauseButton = base.GetTemplateChild(MediaControls.PlayPauseButtonName) as CheckBox;
            this.StopButton = base.GetTemplateChild(MediaControls.StopButtonName) as Button;
            this.MuteButton = base.GetTemplateChild(MediaControls.MuteButtonName) as ToggleButton;
            this.VolumeSlider = base.GetTemplateChild(MediaControls.VolumeSliderName) as Slider;
            this.DownloadSlider = base.GetTemplateChild(MediaControls.DownloadSliderName) as Slider;
            this.TimelineSlider = base.GetTemplateChild(MediaControls.TimelineSliderName) as Slider;
            this.TotalDuration = base.GetTemplateChild(MediaControls.TotalDurationName) as TextBlock;
            this.CurrentDuration = base.GetTemplateChild(MediaControls.CurrentDurationName) as TextBlock;
            this.FullScreenButton = base.GetTemplateChild(MediaControls.FullScreenButtonName) as ToggleButton;

            if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            {
                Binding canSeekBinding = new Binding("CanSeek");
                canSeekBinding.Source = ViewModel;
                canSeekBinding.Mode = BindingMode.OneWay;

                Binding canInteractBinding = new Binding("CanInteract");
                canInteractBinding.Source = ViewModel;
                canInteractBinding.Mode = BindingMode.OneWay;

                if (this.ForwardButton != null)
                {
                    if (fwHandler == null)
                    {
                        fwHandler = delegate(object sender, RoutedEventArgs e)
                        {
                            ViewModel.Action(new ActionBag() { Action = PlayerAction.MoveForward, Param = null });
                        };
                    }
                    this.ForwardButton.Click += fwHandler;
                    this.ForwardButton.SetBinding(Button.IsEnabledProperty, canSeekBinding);
                }

                if (this.BackwardButton != null)
                {
                    if (bckwdHandler == null)
                    {
                        bckwdHandler = delegate(object sender, RoutedEventArgs e)
                        {
                            ViewModel.Action(new ActionBag() { Action = PlayerAction.MoveBackward, Param = null });
                        };
                    }
                    this.BackwardButton.Click += bckwdHandler;
                    this.BackwardButton.SetBinding(Button.IsEnabledProperty, canSeekBinding);
                }

                if (this.PlayPauseButton != null)
                {
                    if (playPauseCheckhandler == null)
                    {
                        playPauseCheckhandler = delegate(object sender, RoutedEventArgs e)
                        {
                            ViewModel.Action(new ActionBag() { Action = PlayerAction.Play, Param = null });
                        };
                    }
                    this.PlayPauseButton.Checked += playPauseCheckhandler;
                    this.PlayPauseButton.SetBinding(ButtonBase.IsEnabledProperty, canInteractBinding);

                    if (playPauseUnCheckHandler == null)
                    {
                        playPauseUnCheckHandler = delegate(object sender, RoutedEventArgs e)
                        {
                            ViewModel.Action(new ActionBag() { Action = PlayerAction.Pause, Param = null });
                        };
                    }
                    this.PlayPauseButton.Unchecked += playPauseUnCheckHandler;

                    Binding checkedBinding = new Binding("Playing");
                    checkedBinding.Source = ViewModel;
                    checkedBinding.Mode = BindingMode.TwoWay;

                    this.PlayPauseButton.SetBinding(CheckBox.IsCheckedProperty, checkedBinding);
                }

                if (this.StopButton != null)
                {
                    if (stopHandler == null)
                    {
                        stopHandler = delegate(object sender, RoutedEventArgs e)
                        {
                            ViewModel.Action(new ActionBag() { Action = PlayerAction.Stop, Param = null });
                        };
                    }
                    this.StopButton.Click += stopHandler;
                    this.StopButton.SetBinding(ButtonBase.IsEnabledProperty, canInteractBinding);
                }

                if (this.MuteButton != null)
                {
                    if (muteCheckHandler == null)
                    {
                        muteCheckHandler = delegate(object sender, RoutedEventArgs e)
                        {
                            ViewModel.Action(new ActionBag() { Action = PlayerAction.Mute, Param = null });
                        };
                    }
                    this.MuteButton.Checked += muteCheckHandler;

                    if (muteUncheckHandler == null)
                    {
                        muteUncheckHandler = delegate(object sender, RoutedEventArgs e)
                        {
                            ViewModel.Action(new ActionBag() { Action = PlayerAction.UnMute, Param = null });
                        };
                    }
                    this.MuteButton.Unchecked += muteUncheckHandler;

                    Binding checkedBinding = new Binding("Muted");
                    checkedBinding.Source = ViewModel;
                    checkedBinding.Mode = BindingMode.TwoWay;

                    this.MuteButton.SetBinding(ToggleButton.IsCheckedProperty, checkedBinding);
                }

                if (VolumeSlider != null)
                {
                    if (volumeHandler == null)
                    {
                        volumeHandler = delegate(object sender, RoutedPropertyChangedEventArgs<double> e)
                        {
                            if (((PlayerModel)ViewModel).Volume != e.NewValue)
                            {
                                ViewModel.Action(new ActionBag() { Action = PlayerAction.AdjustVolume, Param = e.NewValue });
                            }
                        };
                    }
                    this.VolumeSlider.ValueChanged += volumeHandler;

                    this.VolumeSlider.Maximum = 1;
                    this.VolumeSlider.SmallChange = .125;
                    this.VolumeSlider.LargeChange = .125;

                    Binding volBinding = new Binding("Volume");
                    volBinding.Source = ViewModel;
                    volBinding.Mode = BindingMode.TwoWay;

                    this.VolumeSlider.SetBinding(Slider.ValueProperty, volBinding);
                    this.VolumeSlider.Value = .5;
                }

                if (DownloadSlider != null)
                {
                    this.DownloadSlider.Maximum = 1;
                    this.DownloadSlider.SmallChange = .01;
                    this.DownloadSlider.LargeChange = .01;

                    Binding dwnldBinding = new Binding("DownloadProgress");
                    dwnldBinding.Source = ViewModel;
                    dwnldBinding.Mode = BindingMode.OneWay;

                    this.DownloadSlider.SetBinding(Slider.ValueProperty, dwnldBinding);
                    this.DownloadSlider.IsHitTestVisible = false;
                }

                if (TimelineSlider != null)
                {
                    if (timelineHandler == null)
                    {
                        timelineHandler = delegate(object sender, RoutedPropertyChangedEventArgs<double> e)
                        {
                            double tValue = ((PlayerModel)ViewModel).DurationProgress;
                            if (e.NewValue != tValue)
                            {
                                ViewModel.Action(new ActionBag() { Action = PlayerAction.AdjustTimeline, Param = e.NewValue });
                            }
                        };
                    }

                    this.TimelineSlider.ValueChanged += timelineHandler;

                    this.TimelineSlider.Maximum = 1;
                    this.TimelineSlider.SmallChange = .01;
                    this.TimelineSlider.LargeChange = .01;

                    Binding tmlnBinding = new Binding("DurationProgress");
                    tmlnBinding.Source = ViewModel;
                    tmlnBinding.Mode = BindingMode.TwoWay;

                    this.TimelineSlider.SetBinding(Slider.ValueProperty, tmlnBinding);
                    this.TimelineSlider.SetBinding(Slider.IsEnabledProperty, canInteractBinding);
                }

                if (CurrentDuration != null)
                {
                    Binding txtBinding = new Binding("Position");
                    txtBinding.Converter = new TimeSpanToStringConverter();
                    txtBinding.Source = ViewModel;
                    txtBinding.Mode = BindingMode.OneWay;

                    this.CurrentDuration.SetBinding(TextBlock.TextProperty, txtBinding);
                }

                if (TotalDuration != null)
                {
                    Binding txtBinding = new Binding("Duration");
                    txtBinding.Converter = new TimeSpanToStringConverter();
                    txtBinding.Source = ViewModel;
                    txtBinding.Mode = BindingMode.OneWay;

                    this.TotalDuration.SetBinding(TextBlock.TextProperty, txtBinding);
                }

                if (FullScreenButton != null)
                {
                    Binding checkBinding = new Binding("IsFullScreen");
                    checkBinding.Source = ViewModel;
                    checkBinding.Mode = BindingMode.TwoWay;

                    this.FullScreenButton.SetBinding(ToggleButton.IsCheckedProperty, checkBinding);
                }
            }

            this.IsMouseOver = false;
            UpdateVisualState();
        }
    }
}
